﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
using System.Configuration;
using PizzaService.Model;
using PizzaService.Connector;
using System.Collections.ObjectModel;
using PizzaService.Events;
using PizzaService.Properties;
using System.Data.SqlClient;
using PizzaService.Entities;
using PizzaService.View;

namespace PizzaService.Controller
{
    public class PizzaController
    {
        public PizzaViewModel MainViewModel { get; set; }

        public LoginViewModel LoginWindowViewModel { get; set; }

        public CreateNewFoodModel NewFoodModel { get; set; }

        public Kunde EditKundeViewModel { get; set; }

        public EditFoodViewModel EditFViewModel { get; set; }

        public Bestellung OpenedOrderViewModel { get; set; }

        private Kunde m_OpenedCustomer;


        #region event
        public delegate void ExceptionEventHandler(object sender, ExceptionEvent e);

        public event ExceptionEventHandler ExceptionEv;

        #endregion

        PizzaDAL Connector;

        /// <summary>
        /// Constructor
        /// </summary>
        public PizzaController()
        {
            MainViewModel = new PizzaViewModel();
            LoginWindowViewModel = new LoginViewModel();
            EditFViewModel = new EditFoodViewModel();
            MainViewModel.Bestellung = new Bestellung();
            MainViewModel.Bestellung.Speisen = new ObservableCollection<Speise>();
            MainViewModel.Bestellungen = new ObservableCollection<Bestellung>();
            pushConfigToModel();
            
        }

        void Connector_ExceptionEv(object sender, ExceptionEvent e)
        {
            RaiseExceptionEvent(e.ExceptionText);
        }

        /// <summary>
        /// TODO: This event must be subscribed from the MainWindow
        /// </summary>
        /// <param name="exceptionText"></param>
        protected void RaiseExceptionEvent(string exceptionText)
        {
            // Raise the event by using the () operator. 
            if (ExceptionEv != null)
                ExceptionEv(this, new ExceptionEvent(exceptionText));
        }

        /// <summary>
        /// Generate our ViewModel for the ListViews of Food directly from our DB
        /// </summary>
        private void populateAddFoodModel(ObservableCollection<Speise> speisen)
        {
            MainViewModel.Pizzen = new ObservableCollection<Speise>();
            MainViewModel.Pasta = new ObservableCollection<Speise>();
            MainViewModel.Salate = new ObservableCollection<Speise>();

            string zutatenList = String.Empty;

            foreach (var item in speisen)
            {
                if (item.Typ == Speise.SpeiseTyp.Pizza)
                    MainViewModel.Pizzen.Add(item);
                else if (item.Typ == Speise.SpeiseTyp.Pasta)
                    MainViewModel.Pasta.Add(item);
                else if (item.Typ == Speise.SpeiseTyp.Salat)
                    MainViewModel.Salate.Add(item);
            }
        }

        public bool GenerateModel()
        {
            try
            {
                MainViewModel.Kunden = Connector.Kunden;
                populateAddFoodModel(Connector.Speisen);
                //MainViewModel.Speisen = Connector.Speisen;
                MainViewModel.Zutaten = Connector.Zutaten;

                EditFViewModel.AllExtraZutaten = Connector.ExtraZutaten;

                MainViewModel.Bestellungen = Connector.Bestellungen;

                

            }
            catch (Exception ex)
            {
                return false;
            }

            

            return true;
        }

        private void pushConfigToModel()
        {
            var connectionstringParser = new SqlConnectionStringBuilder(Settings.Default.DB_ConnectionString);

            LoginWindowViewModel.User = connectionstringParser.UserID;
            LoginWindowViewModel.Database = connectionstringParser.InitialCatalog;
            LoginWindowViewModel.Server = connectionstringParser.DataSource;
        }

        public void SetConnectionString(string connectionString)
        {
            Settings.Default.DB_ConnectionString = connectionString;
            Connector = new PizzaDAL(connectionString);
            Connector.ExceptionEv += new PizzaDAL.ExceptionEventHandler(Connector_ExceptionEv);
            Settings.Default.Save();
        }

        internal void OpenEditCustomers(Kunde kunde)
        {
            if (Connector != null)
            {
                EditKundeViewModel = new Kunde();

                m_OpenedCustomer = kunde;

                EditKundeViewModel.ID = kunde.ID;
                EditKundeViewModel.Name = kunde.Name;
                EditKundeViewModel.Vorname = kunde.Vorname;
                EditKundeViewModel.Strasse = kunde.Strasse;
                EditKundeViewModel.Hausnummer = kunde.Hausnummer;
                EditKundeViewModel.Ort = kunde.Ort;
                EditKundeViewModel.PLZ = kunde.PLZ;
                EditKundeViewModel.Telefonnummer = kunde.Telefonnummer;
                EditKundeViewModel.Mail = kunde.Mail;

                EditCustomerWindow window = new EditCustomerWindow(false);
                window.Show();
            }
            else
                RaiseExceptionEvent("Bitte loggen Sie sich erst ein");
        }

        internal void SaveCustomer()
        {
            if (Connector != null)
            {
                if (Connector.UpdateKunde(m_OpenedCustomer, EditKundeViewModel))
                {
                    m_OpenedCustomer.Name = EditKundeViewModel.Name;
                    m_OpenedCustomer.Vorname = EditKundeViewModel.Vorname;
                    m_OpenedCustomer.Strasse = EditKundeViewModel.Strasse;
                    m_OpenedCustomer.Hausnummer = EditKundeViewModel.Hausnummer;
                    m_OpenedCustomer.Ort = EditKundeViewModel.Ort;
                    m_OpenedCustomer.PLZ = EditKundeViewModel.PLZ;
                    m_OpenedCustomer.Telefonnummer = EditKundeViewModel.Telefonnummer;
                    m_OpenedCustomer.Mail = EditKundeViewModel.Mail;
                }
            }
            else
                RaiseExceptionEvent("Bitte loggen Sie sich erst ein");
        }

        internal void CreateNewCustomer()
        {
            if (Connector != null)
            {
                EditKundeViewModel = new Kunde();

                EditCustomerWindow window = new EditCustomerWindow(true);
                window.Show();
            }
            else
                RaiseExceptionEvent("Bitte loggen Sie sich erst ein");
        }

        internal void SaveNewCustomer()
        {
            long id_Kunde = Connector.CreateKunde(EditKundeViewModel);
            if (id_Kunde != -1)
            {
                EditKundeViewModel.ID = id_Kunde;
                MainViewModel.Kunden.Add(EditKundeViewModel);
            }
        }

        internal void DeleteCustomer(Kunde temp)
        {
            if (Connector != null)
            {
                if (Connector.DeleteKunde(temp))
                {
                    MainViewModel.Kunden.Remove(temp);
                }
            }
            else
                RaiseExceptionEvent("Bitte loggen Sie sich erst ein");
        }

        internal void Logout()
        {
            Connector = null;
            MainViewModel.Kunden = null;
        }

        internal void OpenEditFood(object item, string btnSender)
        {
            //Speise food = (Speise)item;

            Speise speise = new Speise();

            speise.Zutaten = new ObservableCollection<Zutat>((item as Speise).Zutaten);

            speise.ID = (item as Speise).ID;
            speise.Name = (item as Speise).Name;
            speise.Preis_groß = (item as Speise).Preis_groß;
            speise.Preis_klein = (item as Speise).Preis_klein;
            speise.GesamtPreis = (item as Speise).GesamtPreis;
            speise.Typ = (item as Speise).Typ;

            if (speise.ExtraZutaten == null)
                speise.ExtraZutaten = new ObservableCollection<ExtraZutat>();
            else
                speise.ExtraZutaten = new ObservableCollection<ExtraZutat>((item as Speise).ExtraZutaten);

            if (btnSender == "BtnAddSmall")
            {
                speise.Size = Speise.SizeEnum.Klein;
                speise.AktuellerPizzaPreis = speise.Preis_klein;
            }
            else if (btnSender == "BtnAddBig")
            {
                speise.Size = Speise.SizeEnum.Groß;
                speise.AktuellerPizzaPreis = speise.Preis_groß;
            }

            EditFViewModel.Food = speise;

            showEditFoodWindow();
        }

        private void showEditFoodWindow()
        {
            EditFoodWindow foodWindow = new EditFoodWindow();
            foodWindow.Show();
        }

        internal void AddExtraZutat(object item)
        {
            ExtraZutat food = (ExtraZutat)item;

            if (!EditFViewModel.Food.ExtraZutaten.Contains(food))
            {
                EditFViewModel.Food.ExtraZutaten.Add(food);

                EditFViewModel.GesamtZutatenPreis += food.Preis;
            }
        }

        internal void RemoveExtraZutat(object item)
        {
            ExtraZutat food = (ExtraZutat)item;

            EditFViewModel.Food.ExtraZutaten.Remove(food);

            EditFViewModel.GesamtZutatenPreis -= food.Preis;
        }

        internal void AddFood()
        {
            EditFViewModel.Food.GesamtPreis = EditFViewModel.GesamtZutatenPreis + EditFViewModel.Food.AktuellerPizzaPreis;

            MainViewModel.Bestellung.Speisen.Add(EditFViewModel.Food);

            calculateOrderTotal();

            EditFViewModel.GesamtZutatenPreis = 0.0m;
            EditFViewModel.Food = null;

        }

        private void calculateOrderTotal()
        {
            MainViewModel.Bestellung.Summe = 0.0m;

            foreach (var item in MainViewModel.Bestellung.Speisen)
            {
                MainViewModel.Bestellung.Summe += item.AktuellerPizzaPreis;
            }

            if (MainViewModel.Bestellung.Summe <= 15.0m)
                MainViewModel.Bestellung.Lieferpauschale = 2.50m;
            else
                MainViewModel.Bestellung.Lieferpauschale = 0.00m;

            MainViewModel.Bestellung.Summe += MainViewModel.Bestellung.Lieferpauschale;
        }

        internal void RemoveFood(object item)
        {
            if (item is Speise)
            {
                MainViewModel.Bestellung.Speisen.Remove(item as Speise);

                calculateOrderTotal();
            }
        }

        internal void AssignCustomerToOrder(Kunde kunde)
        {
            MainViewModel.Bestellung.Kunde = kunde;
        }

        internal void ResetOrder()
        {
            MainViewModel.Bestellung.Speisen = new ObservableCollection<Speise>();
            MainViewModel.Bestellung.Kunde = new Kunde();
            MainViewModel.Bestellung.Lieferpauschale = 0m;
            MainViewModel.Bestellung.Summe = 0m;
        }

        internal void CompleteOrder()
        {
            if (MainViewModel.Bestellung.Kunde != null && MainViewModel.Bestellung.Speisen.Count > 0)
            {
                Bestellung newOrder = new Bestellung();

                newOrder.Kunde = new Kunde(MainViewModel.Bestellung.Kunde);
                newOrder.Lieferpauschale = MainViewModel.Bestellung.Lieferpauschale;
                newOrder.Summe = MainViewModel.Bestellung.Summe;
                newOrder.Speisen = new ObservableCollection<Speise>(MainViewModel.Bestellung.Speisen);
                newOrder.Date = DateTime.Now;
                newOrder.Status = Bestellung.BestellStatus.WirdBearbeitet;

                long id_Bestellung = Connector.CreateNewOrder(newOrder);

                if (id_Bestellung != -1)
                {
                    newOrder.ID_Bestellung = id_Bestellung;
                    MainViewModel.Bestellungen.Add(newOrder);

                    ResetOrder();
                }
                else
                {
                    // sollte niemals passieren, aber wer weiß :)
                    RaiseExceptionEvent("Etwas ist schief gegangen! Bitte rufen Sie einen Administrator!");
                }
            }
            else
            {
                RaiseExceptionEvent("Ein Kunde muss ausgewählt sein und mindestens eine Speise ausgewählt worden sein");
            }
        }

        internal void UnassignCustomerFromOrder()
        {
            MainViewModel.Bestellung.Kunde = null;
        }

        internal void OpenShowOrder(Bestellung bestellung)
        {
            OpenedOrderViewModel = bestellung;

            ShowOrder orderWindow = new ShowOrder((int)bestellung.Status);

            orderWindow.Show();
        }

        internal bool CreateNewPizza(string type)
        {
            int idFood = -1;
                switch (type)
                {
                    case "Pizza":
                        NewFoodModel.Food.Typ = Speise.SpeiseTyp.Pizza;
                        idFood = Connector.CreateSpeise(NewFoodModel.Food);

                        if (idFood != -1)
                        {
                            NewFoodModel.Food.ID = idFood;
                            MainViewModel.Pizzen.Add(new Speise(NewFoodModel.Food));
                            return true;
                        }
                        break;
                    case "Pasta":
                        NewFoodModel.Food.Typ = Speise.SpeiseTyp.Pasta;
                        idFood = Connector.CreateSpeise(NewFoodModel.Food);
                        if (idFood != -1)
                        {
                            NewFoodModel.Food.ID = idFood;
                            MainViewModel.Pasta.Add(new Speise(NewFoodModel.Food));
                            return true;
                        }
                        break;
                    case "Salat":
                        NewFoodModel.Food.Typ = Speise.SpeiseTyp.Salat;

                        idFood = Connector.CreateSpeise(NewFoodModel.Food);
                        if (idFood != -1)
                        {
                            NewFoodModel.Food.ID = idFood;
                            MainViewModel.Salate.Add(new Speise(NewFoodModel.Food));
                            return true;
                        }
                        break;
                }

                //if (Connector.CreateSpeise(NewFoodModel.Food))
                //{
                //    MainViewModel.Speisen.Add(new Speise(NewFoodModel.Food));
                //    return true;
                //}

                return false;
            
        }

        internal void OpenCreateNewPizzaWindow()
        {
            NewFoodModel = new CreateNewFoodModel();

            NewFoodModel.Types = new List<string>();

            NewFoodModel.Types.Add("Pizza");
            NewFoodModel.Types.Add("Salat");
            NewFoodModel.Types.Add("Pasta");

            NewFoodModel.Zutaten = MainViewModel.Zutaten;
            NewFoodModel.Food = new Speise();
            NewFoodModel.Food.Zutaten = new ObservableCollection<Zutat>();

            CreateNewFoodWindow newFoodWindow = new CreateNewFoodWindow();
            newFoodWindow.Show();
        }

        internal void AddZutat(object item)
        {
            if (item is Zutat)
            {
                NewFoodModel.Food.Zutaten.Add(item as Zutat);
            }
        }

        internal void RemoveZutat(object item)
        {
            if (item is Zutat)
            {
                NewFoodModel.Food.Zutaten.Remove(item as Zutat);
            }
        }

        internal void SaveOrderState(int p)
        {
            OpenedOrderViewModel.Status = (Bestellung.BestellStatus)p;
            Connector.SaveOrderState(OpenedOrderViewModel, p);
        }

        internal void DeleteFood(object p)
        {
            if (p is Speise)
            {
                Speise sp = (Speise)p;

                if (Connector.DeleteFood(sp.ID))
                {
                    switch (sp.Typ)
                    {
                        case Speise.SpeiseTyp.Pizza:
                            MainViewModel.Pizzen.Remove(sp);
                            break;
                        case Speise.SpeiseTyp.Pasta:
                            MainViewModel.Pasta.Remove(sp);
                            break;
                        case Speise.SpeiseTyp.Salat:
                            MainViewModel.Salate.Remove(sp);
                            break;
                    }
                }
            }
        }
    }
}
